<?php

namespace App\Logic\Account;

use App\Component\LogListForm;
use App\Core\BaseCore;
use App\Core\BaseForm;
use App\Core\BaseListForm;
use App\Core\BaseModel;
use App\Core\Exception\DefaultException;
use App\Core\Exception\ValidationException;
use App\Core\Output;
use App\Enums\ValidateEnums;
use App\Logic\Account\Form\CancelCashoutForm;
use App\Logic\Account\Form\CashoutListForm;
use App\Logic\Account\Form\FinshCashoutForm;
use App\Logic\Account\Form\SubmitCashoutProfitForm;
use App\Model\Account\CashoutModel;
use App\Logic\Account\Form\SubmitCashoutForm;
use App\Model\Account\RechargeModel;
use App\Model\Member\MemberModel;
use App\Util\ArrayHelper;
use App\Util\CommonHelper;
use App\Util\UserIdentityHelper;
use EasySwoole\Component\Di;
use EasySwoole\Component\Singleton;
use EasySwoole\EasySwoole\Config as ESConfig;
use EasySwoole\Http\Request;
use EasySwoole\ORM\DbManager;
use EasySwoole\ORM\Exception\Exception;
use EasySwoole\Redis\Redis;
use EasySwoole\RedisPool\RedisPool;
use EasySwoole\Utility\Random;
use EasySwoole\Validate\Validate;
use Throwable;

class CashoutService extends BaseCore
{

    use Singleton;

    /**
     * 字典数据
     * @param Request $request
     * @return Output
     * @throws Exception
     * @throws Throwable
     */
    public function getDict(Request $request) : Output
    {
        $params = $request->getQueryParams();
        $result = [
            'account_type' => ArrayHelper::keyArrayToList(CashoutModel::getAccountTypeDict()),
            'cash_state'   => ArrayHelper::keyArrayToList(CashoutModel::getCashStateDict()),
            'payment_type' => ArrayHelper::keyArrayToList(CashoutModel::getPaymentTypeDict()),
        ];
        /**提现限额信息一并返回*/
        $ext = $params['ext'] ?? 0;
        if($ext){
            $user_id = UserIdentityHelper::getId();
            /**本金账户最大可提现额度*/
            $result['max_score'] = $this->getPrincipalAccountMaxCashoutAmount($user_id);
            /**收益账户最大可提现额度*/
            $result['max_profit_score'] = $this->getProfitAccountMaxCashoutAmount($user_id);
            /**提现日期*/
            $result['cashout_allow_date'] = '每月' . implode('日、', CashoutModel::ALLOW_DATE) . '日可提现';
            /**今天是否可提现*/
            $result['today_is_cashout_allow'] = in_array(date('j'), CashoutModel::ALLOW_DATE) ? 1 : 0;
            /**默认提现账户*/
            $result['default_account_type'] = CashoutModel::ACCOUNT_TYPE_PROFIT;
            /**默认提现方式户*/
            $result['default_payment_type'] = CashoutModel::PAYMENT_USDT;
        }
        return $this->success($result);
    }

    /**
     * 提现 - 本金账户
     * @param $data
     * @return Output
     * @throws DefaultException
     * @throws Exception
     * @throws Throwable
     * @throws \EasySwoole\Mysqli\Exception\Exception
     */
    public function create($data) : Output
    {
        $cashoutForm = new SubmitCashoutForm($data);

        $result = $cashoutForm->submit();
        return $result;
    }

    /**
     * 提现 - 收益账户
     * @param $data
     * @return Output
     * @throws DefaultException
     * @throws Exception
     * @throws Throwable
     * @throws \EasySwoole\Mysqli\Exception\Exception
     */
    public function profit($data) : Output
    {
        $cashoutProfitForm = new SubmitCashoutProfitForm($data);

        $result = $cashoutProfitForm->submit();
        return $result;
    }

    /**提现中和已提现总金额*/
    public function getCashoutAmount($user_id)
    {
        $where = [
            'user_id' => $user_id,
            'account_type' => CashoutModel::ACCOUNT_TYPE_FUNDS,
            'cash_state' => [
                [CashoutModel::INPROGRESS, CashoutModel::FINISHED], 'IN'
            ],
        ];
        $cashout_amount = CashoutModel::create()
            ->where($where)
            ->sum('amout');
        return $cashout_amount ?? 0;
    }
    /**
     * 计算本金账户locked_day时间前充值的总金额
     */
    public function getPrincipalAccountRechargeScore($user_id)
    {
        $member = MemberModel::create()->get($user_id);
        /**计算locked_day时间前充值的总score RechargeModel*/
        $locked_day = $member->locked_day;
        $recharge_score = 0;
        if($locked_day > 0){
            $recharge_score = RechargeModel::create()
                ->where('user_id', $user_id)
                ->where('recharge_state', RechargeModel::FINISHED)
                ->where('created_at', date('Y-m-d H:i:s', strtotime("-$locked_day day")), '<')
                ->sum('score');
        }
        return $recharge_score ?? 0;
    }

    /**
     * 计算本金账户不可提现金额
    */
    public function getPrincipalAccountUnableCashoutAmount($user_id)
    {
        $member = MemberModel::create()->get($user_id);
        /**取出本金账户不可提现天数:locked_day,计算locked_day时间内充值的总score RechargeModel*/
        $locked_day = $member->locked_day;
        $recharge_score = 0;
        if($locked_day > 0){
            $recharge_score = RechargeModel::create()
                ->where('user_id', $user_id)
                ->where('recharge_state', RechargeModel::FINISHED)
                ->where('created_at', date('Y-m-d H:i:s', strtotime("-$locked_day day")), '>')
                ->sum('score');
        }
        return $recharge_score ?? 0;
    }

    /**
     * 计算本金账户最大可提现金额
    */
    public function getPrincipalAccountMaxCashoutAmount($user_id)
    {
        $member = MemberModel::create()->get($user_id);
        $score = $member->score;
        $locked_day = $member->locked_day;
        if($locked_day == 0){
            /**不锁定,全部可提现*/
            return $score;
        }
        /**锁定期之前充值总金额*/
        $recharge_score = $this->getPrincipalAccountRechargeScore($user_id);
        /**提现中和已提现总金额*/
        $cashout_amount = $this->getCashoutAmount($user_id);
        $max = bcsub($recharge_score, $cashout_amount, 2);
        $max = min($score, $max);
        return $max > 0 ? $max : 0;
    }

    /**
     * 计算收益账户最大可提现金额
     * 收益账户两周提现一次，每次提现100起，只能是整数倍
    */
    public function getProfitAccountMaxCashoutAmount($user_id)
    {
        $member = MemberModel::create()->get($user_id);
        $score = $member->profit_score;
        return floor($score/100) * 100;
    }

    /**
     * 判断收益账户是否可以提现
     * 收益账户两周提现一次，每次提现100起，只能是整数倍
    */
    public function isProfitAccountCanCashout($user_id)
    {
        //判断CashoutModel::PROFIT_PERIOD天内是否有提现记录 提现状态为 INPROGRESS:进行中或FINISHED:已完成
        $cashout_count = CashoutModel::create()
            ->where('user_id', $user_id)
            ->where('account_type', CashoutModel::ACCOUNT_TYPE_PROFIT)
            ->where('cash_state', CashoutModel::INPROGRESS)
            ->where('created_at', date('Y-m-d H:i:s', strtotime("-".CashoutModel::PROFIT_PERIOD." day")), '>')
            ->count();
        return $cashout_count == 0;
    }

    /**
     * 提现列表
     * @param Request $request
     * @return Output
     * @throws DefaultException
     * @throws Exception
     * @throws Throwable
     * @throws \EasySwoole\Mysqli\Exception\Exception
     * @throws \EasySwoole\Redis\Exception\RedisException
     */
    public function getLists(Request $request){
        $params    = $request->getQueryParams();
        $cache     = RedisPool::defer();
        $cache_key = "cashoutCache:lists:" . json_encode($params);
        if ($cache_data = $cache->get($cache_key)) { //缓存存在
            $data = json_decode($cache_data, true);
        } else {
            $form = new CashoutListForm($params, $request);
            $data = $form->lists();
            $cache->set($cache_key, json_encode($data), BaseModel::CACHE_EXPIRE);
        }

        return $this->success($data);
    }

    /**
     * 提现到账
     * @param $data
     * @return Output
     * @throws DefaultException
     * @throws Exception
     * @throws Throwable
     * @throws \EasySwoole\Mysqli\Exception\Exception
     */
    public function finish($data) : Output
    {
        $cashoutForm = new FinshCashoutForm($data);

        $result = $cashoutForm->submit();
        return $result;
    }

    /**
     * 取消提现
     * @param $data
     * @return Output
     * @throws DefaultException
     * @throws Exception
     * @throws Throwable
     * @throws \EasySwoole\Mysqli\Exception\Exception
     */
    public function cancel($data) : Output
    {
        $cashoutForm = new CancelCashoutForm($data);

        $result = $cashoutForm->submit();
        return $result;
    }


}
